#pragma once

#include <cuda_runtime.h>

#include <algorithm/analytical_model/algorithm/cuda/Utils.h>
#include <algorithm/analytical_model/algorithm/cuda/inter_op/Data.h>
#include <utils/config.h>

#include <driver_types.h>
#include <vector>

namespace solar::cuda
{
    class RectangleGrid;
    
    class ShadowBlockCalculator
    {
        public:
            ShadowBlockCalculator();
            void calculate();
            void calculateCenterBias(float3* d_heliostat_positions);
            void init(FUNC_CONST_INPUT std::vector<inter_op::Float3>& input_vertices);
            [[nodiscard]] auto getResult() const -> float4*;
            [[nodiscard]] auto getMicroHeliostatShadowBlock() const -> bool*;
            void setHelioRowCol(const int2& row_col);
            ~ShadowBlockCalculator();

            // size: n_helio_ * helio_row_col_.x * helio_row_col_.y
            // true表示当前微定日镜上被阴影/遮挡
            bool* d_microhelio_ = nullptr;
            // size: n_helio_ * helio_row_col_.y
            // true表示当前微定日镜的这一行上存在阴影/遮挡
            bool* d_microhelio_per_row_ = nullptr;
            // 将每一面定日镜的0,1,3号顶点复制到GPU数组
            float3* d_verts_ = nullptr;
            // float4数组存储结果，针对每面定日镜一个float4，(x,y,z,n)前三个为重心偏移，n为被遮挡的微定日镜个数
            float4* d_sb_result_ = nullptr;
            // 镜场中的定日镜数量
            int n_helio_{};
            // 定日镜离散大小
            int2 helio_row_col_{};
            // 微定日镜尺寸
            // float helios_pixel_size = 0.01F;
            // 每个定日镜的微定日镜数目
            // int micro_helio_num_foreach_helio{};

            // 定日镜顶点坐标
            std::vector<float3> vertices_;
            // 太阳光线方向
            float3 sun_direction_{};
            // Grid（临时设置，后续需要修改）
            RectangleGrid* rectangle_grid_ = nullptr;
            cudaStream_t stream_ = nullptr;

        private:
            // 拷贝定日镜顶点至GPU数组
            void copyHeliostatVerticesToGPU();
            // 初始化结果数组，全部置零
            void initResultArray();
            // 记录每一面子定日镜是否被阴影遮挡
    };
} // namespace solar::cuda
